home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / maint / part06 < prev    next >
Encoding:
Text File  |  1992-05-13  |  64.9 KB  |  2,482 lines

  1. Newsgroups: comp.sources.unix
  2. From: peirce@gw.wmich.edu (Leonard J. Peirce)
  3. Subject: v26i054: maint - full-screen file and directory maintenance tool, Part06/07
  4. Sender: unix-sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: peirce@gw.wmich.edu (Leonard J. Peirce)
  8. Posting-Number: Volume 26, Issue 54
  9. Archive-Name: maint/part06
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 6 (of 7)."
  18. # Contents:  misc.c.orig
  19. # Wrapped by vixie@cognition.pa.dec.com on Thu May 14 23:05:44 1992
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'misc.c.orig' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'misc.c.orig'\"
  23. else
  24. echo shar: Extracting \"'misc.c.orig'\" \(62428 characters\)
  25. sed "s/^X//" >'misc.c.orig' <<'END_OF_FILE'
  26. X/******************************************************************************
  27. X*******************************************************************************
  28. X
  29. X   Site:    Western Michigan University Academic Computer Center
  30. X
  31. X   System:    Directory/File System Maintenance
  32. X  
  33. X   Program:    maint
  34. X
  35. X   Version=01    Level=00    01/24/92    Leonard J. Peirce
  36. X
  37. X   Purpose:    Miscellaneous routines for MAINT.
  38. X
  39. X   Arguments:    See individual routines.
  40. X
  41. X   External variables:  curr_year
  42. X            spec_win
  43. X            stat_win
  44. X            main_win
  45. X            args
  46. X
  47. X   External functions:
  48. X
  49. X    Defined:  add_filetype, banystr, cat, check_marks, cont_after_stop,
  50. X          follow_link, get_bnum, get_dir, get_dir_mem, get_filemarks,
  51. X          get_num_file, make_ent, make_screen, mystrcpy, mystrmcpy,
  52. X          padcpy, prot_str_to_val, prot_val_to_str, rename, set_args,
  53. X          set_date, set_nodes, set_screen, set_width, spawn,
  54. X          squeeze_str, strindex, strtcpy
  55. X
  56. X    Called:   date_qsort, make_slot, name_qsort, put_pool, put_slot,
  57. X          size_qsort, sort_files
  58. X
  59. X   Files accessed:    See individual routines.
  60. X
  61. X   Return codes:    See individual routines.
  62. X
  63. X   Compiling instructions:    See Makefile.
  64. X
  65. X   Linking instructions:    See Makefile.
  66. X
  67. X   Other information:    (C) Copyright 1992, Leonard J. Peirce
  68. X
  69. X********************************************************************************
  70. X*******************************************************************************/
  71. X
  72. X/******************************************************************************/
  73. X/*                                                                            */
  74. X/*                        # I N C L U D E   F I L E S                         */
  75. X/*                                                                            */
  76. X/******************************************************************************/
  77. X
  78. X#ifdef ultrix
  79. X#include <cursesX.h>
  80. X#else
  81. X#include <curses.h>
  82. X#endif
  83. X#include <sys/param.h>
  84. X#include <malloc.h>
  85. X#include <time.h>
  86. X#include <string.h>
  87. X#if !defined(SYSV) || defined(sun)
  88. X#include <sys/wait.h>
  89. X#endif
  90. X#include <errno.h>
  91. X#include <ctype.h>
  92. X#include <varargs.h>
  93. X#include "maint.h"
  94. X#include <sys/stat.h>
  95. X
  96. X/******************************************************************************/
  97. X/*                                                                            */
  98. X/*                             # D E F I N E S                                */
  99. X/*                                                                            */
  100. X/******************************************************************************/
  101. X
  102. X/******************************************************************************/
  103. X/*                                                                            */
  104. X/*          S T R U C T U R E S ,   U N I O N S ,   T Y P E D E F S           */
  105. X/*                                                                            */
  106. X/******************************************************************************/
  107. X
  108. X/******************************************************************************/
  109. X/*                                                                            */
  110. X/*   E X T E R N A L   D E F I N I T I O N S   &   D E C L A R A T I O N S    */
  111. X/*                                                                            */
  112. X/******************************************************************************/
  113. X
  114. extern     int      curr_year;
  115. X
  116. extern     ENT_DEF  *baseptr;
  117. X
  118. extern     WINDOW      *spec_win,
  119. X          *main_win,
  120. X          *stat_win;
  121. X
  122. extern     ARG_DEF  args;
  123. X
  124. extern     char      *getenv();
  125. X
  126. extern     int      execve(),
  127. X          vfork(),
  128. X          put_slot(),
  129. X          make_slot();
  130. X
  131. extern     u_short  cont_flag;
  132. X
  133. extern     void      put_pool(),
  134. X          date_qsort(),
  135. X          size_qsort(),
  136. X          name_qsort(),
  137. X          sort_files();
  138. X
  139. X     char      *mystrcpy(),
  140. X          *mystrmcpy(),
  141. X          *prot_val_to_str(),
  142. X          *padcpy(),
  143. X          *set_date(),
  144. X          *cat();
  145. X
  146. X#if !defined(SYSV) || defined(sun)
  147. X     long      get_bnum();
  148. X#endif
  149. X
  150. X     int      check_marks(),
  151. X          strtcpy(),
  152. X          follow_link(),
  153. X          make_ent(),
  154. X
  155. X#if defined(SYSV) && !defined(sun)
  156. X          rename(),
  157. X#endif
  158. X
  159. X          strindex();
  160. X
  161. X     u_short  add_filetype();
  162. X
  163. X     short      banystr(),
  164. X          get_num_file(),
  165. X          prot_str_to_val();
  166. X
  167. X     u_char      filetype_char();
  168. X
  169. X     void      set_screen(),
  170. X          set_width(),
  171. X          set_args(),
  172. X          set_nodes(),
  173. X          get_dir_mem(),
  174. X          get_dir(),
  175. X          message(),
  176. X          squeeze_str(),
  177. X          make_screen(),
  178. X          cont_after_stop(),
  179. X          get_filemarks();
  180. X
  181. X/******************************************************************************/
  182. X/*                                                                            */
  183. X/*     S T A T I C   D E F I N I T I O N S   &   D E C L A R A T I O N S      */
  184. X/*                                                                            */
  185. X/******************************************************************************/
  186. X
  187. static     char      *get_name();
  188. X
  189. static     u_short  check_nlen();
  190. X
  191. static     u_char      set_type();
  192. X
  193. X/*******************************************************************************
  194. X********************************************************************************
  195. X
  196. X  Function:    set_screen
  197. X
  198. X  Purpose:    Compute values for parameters that relate to the screen,
  199. X        including number of columns, number of files, and the number
  200. X        of screens needed for the directory.
  201. X
  202. X  Global variables:
  203. X
  204. X    Name            Examine/Modify/Use/Read/Write
  205. X    ----            -----------------------------
  206. X    COLS                    X
  207. X
  208. X  Return Codes:
  209. X
  210. X    Code            Reason
  211. X    ----            ------
  212. X    none
  213. X
  214. X********************************************************************************
  215. X*******************************************************************************/
  216. X
  217. void set_screen(num_screen,scr_file,num_file,slot_width,node_row_max,num_col)
  218. X                    /*******   FORMAL  PARAMETERS   *******/
  219. X     short      *num_screen,        /* number of screens in directory     */
  220. X          *scr_file,        /* number of file slots per screen    */
  221. X           num_file,        /* number of files in directory          */
  222. X          slot_width;        /* width of file slot              */
  223. X     u_short  node_row_max;        /* max. # of rows in node array          */
  224. X     short      *num_col;        /* number of columns for full screen  */
  225. X
  226. X{    /*** set_screen ***/
  227. X
  228. X
  229. X   /* compute the number of files per row of the screen */
  230. X
  231. X   *num_col = (short) COLS/(slot_width + SLOT_GAP + 1);
  232. X
  233. X   if(*num_col == 0)
  234. X      *num_col = 1;            /* must have at least one column      */
  235. X
  236. X   /* now compute how many file slots will fit on a screen */
  237. X
  238. X   *scr_file = *num_col * (short) node_row_max;
  239. X
  240. X   /* compute how many screens will be needed for this directory */
  241. X
  242. X   *num_screen = num_file/(*scr_file);
  243. X
  244. X   if((num_file % (*scr_file)) != 0)
  245. X      *num_screen += 1;
  246. X
  247. X   return;
  248. X             
  249. X}    /*** set_screen ***/
  250. X
  251. X/*******************************************************************************
  252. X********************************************************************************
  253. X
  254. X  Function:    set_nodes
  255. X
  256. X  Purpose:    Initialize the screen slot node pointers for the current
  257. X        directory.
  258. X
  259. X  Global variables:
  260. X
  261. X    Name            Examine/Modify/Use/Read/Write
  262. X    ----            -----------------------------
  263. X    none
  264. X
  265. X  Return Codes:
  266. X
  267. X    Code            Reason
  268. X    ----            ------
  269. X    none
  270. X
  271. X********************************************************************************
  272. X*******************************************************************************/
  273. X
  274. void set_nodes(nodes,node_row_max,scr_file,num_screen,curr_screen,num_file,
  275. X           slot_width,num_col)
  276. X                    /*******   FORMAL  PARAMETERS   *******/
  277. register NODE_DEF nodes[][MAX_NODE_COL+1]; /* screen node matrix          */
  278. X     u_short  node_row_max;        /* max. # of rows in node array          */
  279. X     short      *scr_file,        /* number of files on current screen  */
  280. X           num_screen,        /* number of screens for directory    */
  281. X          curr_screen,        /* current screen              */
  282. X          num_file,        /* number of files in directory          */
  283. X          slot_width,        /* number of characters for file slot */
  284. X          num_col;        /* number of columns per screen          */
  285. X
  286. X{    /*** set_nodes ***/
  287. X                    /********   LOCAL  VARIABLES   ********/
  288. register NODE_DEF *tptr;        /* temporary node pointer          */
  289. register int      i,            /* loop and array index              */
  290. X               j;            /* ditto....                  */
  291. static     short      left_val,        /* left pointer for node          */
  292. X          up_val,        /* up pointer for node              */
  293. X          column_val,        /* current column value              */
  294. X          num_row,        /* number of rows for this screen     */
  295. X          full_row,        /* number of full rows for screen     */
  296. X          full_col;        /* number of full columns          */
  297. X
  298. X
  299. X   if(curr_screen == num_screen)    /* if this is the last page          */
  300. X   {
  301. X      /* recompute the number of columns; it might be different because
  302. X       * this is the last page of the directory
  303. X       */
  304. X
  305. X      /* compute how many files will be on this screen of the directory */
  306. X
  307. X      *scr_file = num_file - (num_col * node_row_max * (curr_screen - 1));
  308. X
  309. X      /* now compute how many columns are needed for the last screen */
  310. X
  311. X      num_col = *scr_file / node_row_max;
  312. X
  313. X      if((*scr_file % node_row_max) != 0)
  314. X     num_col++;
  315. X   }
  316. X   else
  317. X   {
  318. X      /* compute how many files will be on this screen of the directory */
  319. X
  320. X      *scr_file = num_col * (short) node_row_max;
  321. X   }
  322. X
  323. X   if(*scr_file < node_row_max)        /* determine number of rows          */
  324. X      num_row = *scr_file;
  325. X   else
  326. X      num_row = node_row_max;
  327. X
  328. X   left_val = num_col - 1;        /* set left and right pointers          */
  329. X   j = 0;                /* start with the first column          */
  330. X   column_val = 0;            /* cursor on screen starts @ (0,0)    */
  331. X   full_col = *scr_file / node_row_max; /* calculate number of full columns   */
  332. X
  333. X   if(full_col == 0)            /* must have at least one full column */
  334. X      full_col = 1;
  335. X
  336. X   full_row = *scr_file - (full_col * num_row);
  337. X
  338. X   if(full_row == 0)
  339. X      full_row = *scr_file / full_col;
  340. X
  341. X   /* first initialize the node matrix just like it would be a full screen;
  342. X    * then we will "trim" the edges to make sure that things point to the right
  343. X    * places in case the cursor would to need to wrap around the screen
  344. X    */
  345. X
  346. X   up_val = num_row - 1;
  347. X   i = 0;
  348. X
  349. X   while(i < num_row)
  350. X   {
  351. X      j = 0;
  352. X      left_val = num_col - 1;        /* left j value                  */
  353. X      column_val = 0;
  354. X
  355. X      while(j < num_col)
  356. X      {
  357. X     tptr = &(nodes[i][j]);        /* get a pointer to the current node  */
  358. X     tptr->right_col = (j + 1) % num_col;
  359. X     tptr->left_col = left_val;
  360. X     tptr->up_col = j;
  361. X     tptr->down_col = j;
  362. X
  363. X     tptr->right_row = i;
  364. X     tptr->left_row = i;
  365. X     tptr->up_row = up_val;
  366. X     tptr->down_row = (i + 1) % num_row;
  367. X
  368. X     tptr->row = i;
  369. X     tptr->column = column_val;
  370. X     column_val = column_val + slot_width + SLOT_GAP + 1;
  371. X     left_val = (left_val + 1) % num_col;
  372. X     j++;
  373. X      }
  374. X
  375. X      up_val = (up_val + 1) % num_row;
  376. X      i++;
  377. X   }
  378. X
  379. X   /* now trim the edges of the matrix just in case this is the last screen
  380. X    * of the directory
  381. X    */
  382. X
  383. X   /* first go along the top of the screen */
  384. X
  385. X   i = 0;
  386. X
  387. X   for(j = 0; j < num_col; j++)
  388. X   {
  389. X      tptr = &(nodes[i][j]);        /* get a pointer to the node          */
  390. X
  391. X      if(!j)                /* are we in the top left node?          */
  392. X      {
  393. X     /* top left node; the values for going up from this node should
  394. X      * point to bottom node in the last column on the screen
  395. X      */
  396. X
  397. X     tptr->up_row = full_row - 1;
  398. X     tptr->up_col = num_col - 1;
  399. X      }
  400. X      else
  401. X      {
  402. X     tptr->up_col = j - 1;
  403. X     tptr->up_row = num_row - 1;
  404. X      }
  405. X   }
  406. X
  407. X   /* now go along the left of the screen */
  408. X
  409. X   j = 0;
  410. X
  411. X   for(i = 0; i < num_row; i++)
  412. X   {
  413. X      tptr = &(nodes[i][j]);
  414. X
  415. X      if(!i)
  416. X      {
  417. X     /* we are in the top left of the screen; going left from here
  418. X      * should go to the bottom, right-most node
  419. X      */
  420. X
  421. X     tptr->left_row = full_row - 1;
  422. X     tptr->left_col = num_col - 1;
  423. X      }
  424. X      else
  425. X      {
  426. X     if(i < full_row + 1)
  427. X        tptr->left_col = num_col - 1;
  428. X     else
  429. X        tptr->left_col = full_col - 1;
  430. X
  431. X     tptr->left_row = (i - 1) % num_row;
  432. X      }
  433. X   }
  434. X
  435. X   /* trim the bottom full columns */
  436. X
  437. X   i = num_row - 1;
  438. X
  439. X   for(j = 0; j < full_col; j++)
  440. X   {
  441. X      tptr = &(nodes[i][j]);        /* get a pointer to the node          */
  442. X      tptr->down_col = j + 1;
  443. X   }
  444. X
  445. X   /* now go along the right side of the last full column */
  446. X
  447. X   j = full_col - 1;
  448. X
  449. X   for(i = full_row; i < num_row; i++)
  450. X   {
  451. X      tptr = &(nodes[i][j]);
  452. X      tptr->right_row = (i + 1) % num_row;
  453. X      tptr->right_col = 0;
  454. X   }
  455. X
  456. X   /* trim along the last column, whether it be full or not */
  457. X
  458. X   j = num_col - 1;
  459. X
  460. X   for(i = 0; i < full_row; i++)
  461. X   {
  462. X      tptr = &(nodes[i][j]);
  463. X      tptr->right_row = (i + 1) % num_row;
  464. X      tptr->right_col = 0;
  465. X   }
  466. X
  467. X   /* set the last node on the screen; this is a special case */
  468. X
  469. X   tptr = &(nodes[full_row-1][num_col-1]);
  470. X   tptr->down_row = 0;
  471. X   tptr->down_col = 0;
  472. X
  473. X   return;
  474. X
  475. X}    /*** set_nodes ***/
  476. X
  477. X/*******************************************************************************
  478. X********************************************************************************
  479. X
  480. X  Function:    make_ent
  481. X
  482. X  Purpose:    Gather all the information about an individual file, including
  483. X        the protection string and filename that will be displayed on
  484. X        the screen.  This information is stored in the directory entry.
  485. X
  486. X  Global variables:
  487. X
  488. X    Name            Examine/Modify/Use/Read/Write
  489. X    ----            -----------------------------
  490. X    none
  491. X
  492. X  Return Codes:
  493. X
  494. X    Code            Reason
  495. X    ----            ------
  496. X    SUCCESS
  497. X    FAILURE
  498. X
  499. X********************************************************************************
  500. X*******************************************************************************/
  501. X
  502. int make_ent(ent,filename,num_block)
  503. X                    /*******   FORMAL  PARAMETERS   *******/
  504. register ENT_DEF  *ent;            /* pointer to file entry          */
  505. register char      *filename;        /* file to be looked up              */
  506. X     long      *num_block;        /* number of blocks in directory      */
  507. X
  508. X{    /*** make_ent ***/
  509. X                    /********   LOCAL  VARIABLES   ********/
  510. static     int      status;        /* return code status holder          */
  511. static     struct      stat    statbuf;    /* file stat structure              */
  512. X
  513. X
  514. X#if !defined(SYSV) || defined(sun)
  515. X   status = lstat(filename,&statbuf);
  516. X#else
  517. X   status = stat(filename,&statbuf);
  518. X#endif
  519. X
  520. X   if(status != 0)
  521. X      return(FAILURE);
  522. X
  523. X   ent->type = set_type(statbuf.st_mode);
  524. X   ent->prot = statbuf.st_mode;
  525. X   ent->time = statbuf.st_mtime;
  526. X   ent->size = statbuf.st_size;
  527. X   ent->command = NULL;
  528. X   ent->text = NULL;
  529. X   ent->gid = statbuf.st_gid;
  530. X   ent->uid = statbuf.st_uid;
  531. X   ent->name_len = check_nlen(filename);
  532. X
  533. X   /* set the filename that will be displayed on the screen */
  534. X
  535. X   strcpy(ent->scr_name,get_name(filename,&(ent->disp_len),ent->prot,
  536. X      ent->type));
  537. X
  538. X#if defined(SYSV) && !defined(sun)
  539. X   *num_block += kbytes(statbuf.st_size);
  540. X#else
  541. X   *num_block += statbuf.st_blocks;
  542. X#endif
  543. X
  544. X   return(SUCCESS);
  545. X
  546. X}    /*** make_ent ***/
  547. X
  548. X/*******************************************************************************
  549. X********************************************************************************
  550. X
  551. X  Function:    make_screen
  552. X
  553. X  Purpose:    Create the individual screen entries for the current screen
  554. X        of the directory and write them to the virtual display.
  555. X
  556. X        This routine will also clear out the slots on the screen where
  557. X        the files should not appear.  This would happen only on the
  558. X        last page of a directory.
  559. X
  560. X  Global variables:
  561. X
  562. X    Name            Examine/Modify/Use/Read/Write
  563. X    ----            -----------------------------
  564. X    none
  565. X
  566. X  Return Codes:
  567. X
  568. X    Code            Reason
  569. X    ----            ------
  570. X    none
  571. X
  572. X********************************************************************************
  573. X*******************************************************************************/
  574. X
  575. void make_screen(window,nodes,dirptr,args,curr_screen,node_row_max,
  576. X         node_col_max,scr_file,num_slot,slot_width,text_flag)
  577. X                    /*******   FORMAL  PARAMETERS   *******/
  578. X     WINDOW      *window;        /* window to write to              */
  579. X     NODE_DEF nodes[][MAX_NODE_COL+1]; /* screen node matrix          */
  580. X     ENT_DEF  *dirptr;        /* pointer to directory information   */
  581. register ARG_DEF  *args;        /* command-line arguments          */
  582. X     short      curr_screen;        /* current screen number          */
  583. X     u_short  node_row_max,        /* max. # of rows in node array          */
  584. X          node_col_max;        /* max. # of columns in node array    */
  585. register short      scr_file;        /* number of files for current screen */
  586. X     short      num_slot,        /* number of slots per screen          */
  587. X          slot_width,        /* width of a filename screen slot    */
  588. X          text_flag;        /* whether we display text descrips   */
  589. X
  590. X{    /*** make_screen ***/
  591. X                    /********   LOCAL  VARIABLES   ********/
  592. register ENT_DEF  *ent;            /* pointer to current directory entry */
  593. register short      file_count = 0;    /* number of files processed          */
  594. static     int      rend_set,        /* rendition setting for slots          */
  595. X          scr_row,        /* what row on screen to write to     */
  596. X          scr_col;        /* what column on screen to write to  */
  597. static     short      i,            /* loop and array index              */
  598. X          j;            /*  "    "    "     "              */
  599. X     char      buf[BUFSIZ+1];    /* formatting buffer              */
  600. X
  601. X
  602. X   /* get pointer to the first directory entry for the current screen */
  603. X
  604. X   ent = dirptr + (u_long) ((curr_screen - 1) * num_slot);
  605. X   j = 0;
  606. X
  607. X   while((j < node_col_max) && (file_count < scr_file))
  608. X   {
  609. X      i = 0;
  610. X      scr_col = nodes[i][j].column + 1;    /* get column value for now          */
  611. X      scr_row = 0;
  612. X
  613. X      while((i < node_row_max) && (file_count < scr_file))
  614. X      {
  615. X     /* create the screen slot for the file; this included determining
  616. X      * if we need to put something special up in case the file has
  617. X      * some command(s) associated with it
  618. X      */
  619. X
  620. X     rend_set = make_slot(buf,ent,args,slot_width,text_flag);
  621. X
  622. X     /* now write the file information to the screen in the right spot */
  623. X
  624. X     put_slot(window,scr_row,scr_col,buf,rend_set);
  625. X     i++;                /* move to next column              */
  626. X     file_count++;            /* count this file as processed          */
  627. X     scr_row++;            /* move to next row on screen          */
  628. X     ent++;                /* go to next directory entry          */
  629. X      }
  630. X
  631. X      j++;                /* go down the screen node matrix     */
  632. X   }
  633. X
  634. X   if(num_slot > scr_file)        /* do we need to clear out some of    */
  635. X   {                    /* the slots on the screen?          */
  636. X      /* clear out the slots */
  637. X
  638. X      while(i++ < node_row_max)
  639. X      {
  640. X     wmove(window,scr_row++,scr_col);
  641. X     wclrtoeol(window);
  642. X      }
  643. X
  644. X      if(j < node_col_max)
  645. X      {
  646. X     /* we have more than one column to clear out */
  647. X
  648. X     scr_col += slot_width + 1;
  649. X     scr_row = 0;
  650. X
  651. X     while(scr_row < node_row_max)
  652. X     {
  653. X        wmove(window,scr_row++,scr_col);
  654. X        wclrtoeol(window);
  655. X     }
  656. X      }
  657. X   }
  658. X
  659. X   return;
  660. X
  661. X}    /*** make_screen ***/
  662. X
  663. X/*******************************************************************************
  664. X********************************************************************************
  665. X
  666. X  Function:    check_marks
  667. X
  668. X  Purpose:    Check to see if there are any marks in the current directory.
  669. X
  670. X  Global variables:
  671. X
  672. X    Name             Examine/Modify/Use/Read/Write
  673. X    ----            -----------------------------
  674. X    none
  675. X
  676. X  Return Codes:
  677. X
  678. X    Code            Reason
  679. X    ----            ------
  680. X    TRUE            marks exist in current directory
  681. X    FALSE            no marks in current directory
  682. X
  683. X********************************************************************************
  684. X*******************************************************************************/
  685. X
  686. int check_marks(ent,num_files)
  687. X                    /*******   FORMAL  PARAMETERS   *******/
  688. register ENT_DEF  *ent;            /* pointer to current file entry      */
  689. register short      num_files;        /* number of files in directory          */
  690. X
  691. X{    /*** check_marks ***/
  692. X
  693. X   while(num_files--)            /* check all entries if necessary     */
  694. X   {
  695. X      if(ent->command)            /* command for this file?          */
  696. X     return(TRUE);            /* yes, no need to check any more     */
  697. X
  698. X      ent++;                /* nope, go to next entry          */
  699. X   }
  700. X
  701. X   return(FALSE);
  702. X
  703. X}    /*** check_marks ***/
  704. X
  705. X/*******************************************************************************
  706. X********************************************************************************
  707. X
  708. X  Function:      get_dir_mem
  709. X
  710. X  Purpose:    Compute the amount of memory needed for the current directory
  711. X        and allocate it.  Also set the global pointer to the base of
  712. X        the memory so that it may be used for sorting if so desired.
  713. X
  714. X  Global variables:
  715. X
  716. X    Name            Examine/Modify/Use/Read/Write
  717. X    ----            -----------------------------
  718. X    baseptr                  X    X
  719. X
  720. X  Return Codes:
  721. X
  722. X    Code            Reason
  723. X    ----            ------
  724. X    none
  725. X
  726. X********************************************************************************
  727. X*******************************************************************************/
  728. X
  729. void get_dir_mem(dirptr,dirsize,num_file)
  730. X                    /*******   FORMAL  PARAMETERS   *******/
  731. X     ENT_DEF  **dirptr;        /* where to store pointer to memory   */
  732. X     u_int      *dirsize;        /* amount of memory allocated          */
  733. X     short      num_file;        /* number of files in directory          */
  734. X
  735. X{    /*** get_dir_mem ***/
  736. X                    /********   LOCAL  VARIABLES   ********/
  737. X     u_int      memsize;        /* amount of memory to allocated      */
  738. X
  739. X
  740. X   /* allocate enough memory to hold the information about each of the
  741. X    * files in the current directory; we get the amount of memory by multi-
  742. X    * plying the number of files (plus 1, in case we want to sort them) 
  743. X    * in the directory by the length the structure definition that holds
  744. X    * the information about a file
  745. X    */
  746. X
  747. X   /* compute how much memory to allocate */
  748. X
  749. X   memsize = (u_int) ((num_file + 1) * sizeof(ENT_DEF));
  750. X   *dirsize = memsize;
  751. X
  752. X   baseptr = (ENT_DEF *) malloc(memsize);
  753. X
  754. X   if(baseptr == NULL)
  755. X   {
  756. X      exit(CANT_ALLOCATE);
  757. X   }
  758. X   else
  759. X      *dirptr = baseptr;
  760. X
  761. X                    /* memory allocated for the directory */
  762. X   return;
  763. X
  764. X}    /*** get_dir_mem ***/
  765. X
  766. X/*******************************************************************************
  767. X********************************************************************************
  768. X
  769. X  Function:    get_dir
  770. X
  771. X  Purpose:    Get the number of files in the current directory, allocate the
  772. X        necessary memory to store the information about the directory,
  773. X        and obtain the information about the individual files.
  774. X
  775. X  Global variables:
  776. X
  777. X    Name            Examine/Modify/Use/Read/Write
  778. X    ----            -----------------------------
  779. X    none
  780. X
  781. X  Return Codes:
  782. X
  783. X    Code            Reason
  784. X    ----            ------
  785. X    none
  786. X
  787. X********************************************************************************
  788. X*******************************************************************************/
  789. X
  790. void get_dir(dirptr,args,num_block,curr_pool,num_file,pool_length)
  791. X                    /*******   FORMAL  PARAMETERS   *******/
  792. register ENT_DEF  *dirptr;        /* pointer to allocated memory          */
  793. register ARG_DEF  *args;        /* run-time argument flags          */
  794. X     long      *num_block;        /* number of blocks in directory      */
  795. X     POOL_DEF **curr_pool;        /* pointer to current memory pool     */
  796. X     short      *num_file;        /* number of files in directory          */
  797. X     size_t      pool_length;        /* length to allocate for new pools   */
  798. X
  799. X{    /*** get_dir ***/
  800. X                    /********   LOCAL  VARIABLES   ********/
  801. X#if !defined(SYSV)
  802. register struct      direct *dir_ent;    /* pointer to directory file entry    */
  803. X#else
  804. register struct      dirent *dir_ent;    /* Suns use this as well as SysV      */
  805. X#endif
  806. X     size_t      name_length;        /* length of filename              */
  807. X     DIR      *dptr;        /* pointer to directory file          */
  808. X
  809. X
  810. X   dptr = opendir(".");            /* open directory so we can read it   */
  811. X
  812. X   if(dptr == NULL)
  813. X      return;
  814. X
  815. X   /* process all of the directory entries that we can get */
  816. X
  817. X   while((dir_ent = readdir(dptr)) != NULL) 
  818. X   {
  819. X      /*try to make the directory entry for this file */
  820. X
  821. X      if(args->dot_files == TRUE || dir_ent->d_name[0] != '.')
  822. X      {
  823. X     if(make_ent(dirptr,dir_ent->d_name,num_block) == SUCCESS)
  824. X     {
  825. X        /* everything ok so far; store the full filename in a memory pool */
  826. X
  827. X        name_length = strlen(dir_ent->d_name);
  828. X        put_pool(&(dirptr->filename),curr_pool,dir_ent->d_name,name_length,
  829. X             pool_length);
  830. X            dirptr++;
  831. X     }
  832. X     else
  833. X        *num_file -= 1;        /* bummer; subtract one from num_file */
  834. X      }
  835. X   }
  836. X
  837. X   closedir(dptr);
  838. X
  839. X   /* create a dummy entry at the end in case we want to sort */
  840. X
  841. X   if(sizeof(int) == 4)
  842. X   {
  843. X      dirptr->size = 0xEFFFFFFF;
  844. X      dirptr->time = 0xEFFFFFFF;
  845. X   }
  846. X   else
  847. X   {
  848. X      dirptr->size = 0xEFFF;
  849. X      dirptr->time = 0xEFFF;
  850. X   }
  851. X
  852. X   put_pool(&(dirptr->filename),curr_pool,"~~~~~~~~~~",10,pool_length);
  853. X
  854. X   if(args->sort)
  855. X      sort_files(*num_file - 1,args->sort);
  856. X
  857. X/*   *num_block = (long) kbytes(dbtob(*num_block)); */
  858. X   return;
  859. X
  860. X}    /*** get_dir ***/
  861. X
  862. X/*******************************************************************************
  863. X********************************************************************************
  864. X
  865. X  Function:    get_num_file
  866. X
  867. X  Purpose:    Get the number of files in the current directory.
  868. X
  869. X  Global variables:
  870. X
  871. X    Name              Examine/Modify/Use/Read/Write
  872. X    ----            -----------------------------
  873. X    none
  874. X
  875. X  Return Codes:
  876. X
  877. X    Code            Reason
  878. X    ----            ------
  879. X    count            number of files in directory
  880. X      -1            failure
  881. X
  882. X********************************************************************************
  883. X*******************************************************************************/
  884. X
  885. short get_num_file(args)
  886. X                    /*******   FORMAL  PARAMETERS   *******/
  887. register ARG_DEF  *args;        /* run-time arguments              */
  888. X
  889. X{    /*** get_num_file ***/
  890. X                    /********   LOCAL  VARIABLES   ********/
  891. register DIR      *dptr;        /* pointer to directory file entry    */
  892. register short      count;        /* number of files in directory          */
  893. X#if !defined(SYSV)
  894. register struct      direct *dir_ent;    /* pointer to directory file entry    */
  895. X#else
  896. register struct      dirent *dir_ent;    /* Suns use this as well as SysV      */
  897. X#endif
  898. X
  899. X
  900. X   dptr = opendir(".");            /* open the current directory          */
  901. X
  902. X   if(dptr == NULL)
  903. X      return(-1);
  904. X
  905. X   count = 0;
  906. X
  907. X   if(args->dot_files == TRUE)
  908. X   {
  909. X      while(readdir(dptr) != NULL)
  910. X     ++count;
  911. X   }
  912. X   else
  913. X   {
  914. X      while((dir_ent = readdir(dptr)) != NULL)
  915. X      {
  916. X     if(dir_ent->d_name[0] != '.')
  917. X        ++count;
  918. X      }
  919. X   }
  920. X
  921. X   closedir(dptr);
  922. X   return(count);            /* return number of files          */
  923. X
  924. X}    /*** get_num_file ***/
  925. X
  926. X/*******************************************************************************
  927. X********************************************************************************
  928. X
  929. X  Function:    mystrcpy
  930. X
  931. X  Purpose:    Version of strcpy that copies a string and returns a pointer
  932. X        to the null character in the destination string.
  933. X
  934. X  Global variables:
  935. X
  936. X    Name            Examine/Modify/Use/Read/Write
  937. X    ----            -----------------------------
  938. X    none
  939. X
  940. X  Return Codes:
  941. X
  942. X    Code            Reason
  943. X    ----            ------
  944. X    dest - 1        pointer to null character terminating the
  945. X                destionation string
  946. X
  947. X********************************************************************************
  948. X*******************************************************************************/
  949. X
  950. char *mystrcpy(dest,source)
  951. X                    /*******   FORMAL  PARAMETERS   *******/
  952. X     char      *dest,        /* destination string              */
  953. X          *source;        /* source string              */
  954. X
  955. X{    /*** mystrcpy ***/
  956. X
  957. X   while(*dest++ = *source++)        /* copy the source string to the dest */
  958. X      ;
  959. X
  960. X   return(dest - 1);            /* return pointer to null character   */
  961. X
  962. X}    /*** mystrcpy ***/
  963. X
  964. X/*******************************************************************************
  965. X********************************************************************************
  966. X
  967. X  Function:    mystrmcpy
  968. X
  969. X  Purpose:    Version of strncpy that copies exactly n characters and
  970. X        returns a pointer to the null character in the destination
  971. X        string.
  972. X
  973. X  Global variables:
  974. X
  975. X    Name            Examine/Modify/Use/Read/Write
  976. X    ----            -----------------------------
  977. X    none
  978. X
  979. X  Return Codes:
  980. X
  981. X    Code            Reason
  982. X    ----            ------
  983. X    dest - 1        pointer to null character terminating the
  984. X                destionation string
  985. X
  986. X********************************************************************************
  987. X*******************************************************************************/
  988. X
  989. char *mystrmcpy(dest,source,length)
  990. X                    /*******   FORMAL  PARAMETERS   *******/
  991. X     char      *dest,        /* destination string              */
  992. X          *source;        /* source string              */
  993. X     int      length;        /* max. length to copy              */
  994. X
  995. X{    /*** mystrmcpy ***/
  996. X
  997. X   while(*source != '\0' && length-- >= 0)
  998. X      *dest++ = *source++;
  999. X
  1000. X   *(dest - 1) = '\0';            /* make sure it's a string          */
  1001. X   return(dest - 1);            /* return pointer to null character   */
  1002. X
  1003. X}    /*** mystrmcpy ***/
  1004. X
  1005. X/*******************************************************************************
  1006. X********************************************************************************
  1007. X
  1008. X  Function:    prot_val_to_str
  1009. X
  1010. X  Purpose:    Create the string representing the file protection for a
  1011. X        specific file from the integer value for the protection.
  1012. X
  1013. X  Global variables:
  1014. X
  1015. X    Name            Examine/Modify/Use/Read/Write
  1016. X    ----            -----------------------------
  1017. X    none
  1018. X
  1019. X  Return Codes:
  1020. X
  1021. X    Code            Reason
  1022. X    ----             ------
  1023. X    buf            protection string
  1024. X
  1025. X********************************************************************************
  1026. X*******************************************************************************/
  1027. X
  1028. char *prot_val_to_str(prot)
  1029. X                    /*******   FORMAL  PARAMETERS   *******/
  1030. register u_short  prot;            /* protection word value          */
  1031. X
  1032. X{    /*** prot_val_to_str ***/
  1033. X                    /********   LOCAL  VARIABLES   ********/
  1034. register char      *str;            /* pointer to buffer              */
  1035. register short      i,            /* loop and array index              */
  1036. X          j,
  1037. X          k;
  1038. static     char      buf[PROT_MAX+1];    /* where to put the protection string */
  1039. X
  1040. X
  1041. X   /* first determine what type of file it is */
  1042. X
  1043. X   str = buf;
  1044. X
  1045. X   switch(prot & S_IFMT)
  1046. X   {
  1047. X      case(S_IFREG):
  1048. X     *str = '-';            /* regular file                  */
  1049. X     break;
  1050. X      case(S_IFDIR):
  1051. X     *str = 'd';            /* directory                  */
  1052. X     break;
  1053. X      case(S_IFCHR):
  1054. X     *str = 'c';            /* character special file          */
  1055. X     break;
  1056. X      case(S_IFIFO):
  1057. X     *str = 'p';            /* named pipe                  */
  1058. X     break;
  1059. X      case(S_IFBLK):
  1060. X     *str = 'b';            /* block special file              */
  1061. X     break;
  1062. X#if !defined(SYSV) || defined(sun)
  1063. X      case(S_IFLNK):
  1064. X     *str = 'l';            /* symbolic link              */
  1065. X     break;
  1066. X#endif
  1067. X      default:
  1068. X     *str = '-';
  1069. X   }
  1070. X
  1071. X   /* create the permission string */
  1072. X
  1073. X   k = 1;                /* skip over filetype in string          */
  1074. X   j = 0;
  1075. X
  1076. X   for(i = 0; i < 3; i++)
  1077. X   {
  1078. X      if(prot & (S_IREAD >> j))        /* check for read permission          */
  1079. X     *(str + k) = 'r';
  1080. X      else
  1081. X     *(str + k) = '-';
  1082. X
  1083. X      if(prot & (S_IWRITE >> j))    /* check for write permission          */
  1084. X     *(str + k + 1) = 'w';
  1085. X      else
  1086. X     *(str + k + 1) = '-';
  1087. X
  1088. X      if(prot & (S_IEXEC >> j))        /* check for execute permission          */
  1089. X     *(str + k + 2) = 'x';
  1090. X      else
  1091. X     *(str + k + 2) = '-';
  1092. X
  1093. X      k += 3;
  1094. X      j += 3;
  1095. X   }
  1096. X
  1097. X   /* check the setuid bit */
  1098. X
  1099. X   if(prot & S_ISUID)
  1100. X   {
  1101. X      /* setuid is set; now see if it is executable */
  1102. X
  1103. X      if(*(str + 3) == 'x')
  1104. X     *(str + 3) = 's';
  1105. X      else
  1106. X     *(str + 3) = 'S';
  1107. X   }
  1108. X
  1109. X   if(prot & S_ISGID)
  1110. X   {
  1111. X      /* setgid is set; now see if it is executable */
  1112. X
  1113. X      if(*(str + 6) == 'x')
  1114. X     *(str + 6) = 's';
  1115. X      else
  1116. X     *(str + 6) = 'S';
  1117. X   }
  1118. X
  1119. X   if(prot & S_ISVTX)
  1120. X   {
  1121. X      /* sticky bit is set */
  1122. X
  1123. X      *(str + 9) = 't';
  1124. X   }
  1125. X
  1126. X   *(str + PROT_MAX) = '\0';        /* make it a string              */
  1127. X   return(buf);
  1128. X
  1129. X}    /*** prot_val_to_str ***/
  1130. X
  1131. X/*******************************************************************************
  1132. X********************************************************************************
  1133. X
  1134. X  Function:    prot_str_to_val
  1135. X
  1136. X  Purpose:    Given a protection string and the original integer value
  1137. X        for a file's protection, edit the string and if it is valid,
  1138. X        calculate the new protection integer value.
  1139. X
  1140. X  Global variables:
  1141. X
  1142. X    Name            Examine/Modify/Use/Read/Write
  1143. X    ----            -----------------------------
  1144. X    none
  1145. X
  1146. X  Return Codes:
  1147. X
  1148. X    Code            Reason
  1149. X    ----            ------
  1150. X    SUCCESS
  1151. X    FAILURE            invalid protection specification
  1152. X
  1153. X********************************************************************************
  1154. X*******************************************************************************/
  1155. X
  1156. short prot_str_to_val(str,new_val)
  1157. X                    /*******   FORMAL  PARAMETERS   *******/
  1158. register char      *str;            /* protection string              */
  1159. X     u_short  *new_val;        /* calculated protection value          */
  1160. X
  1161. X{    /*** prot_str_to_val ***/
  1162. X
  1163. X                    /********   LOCAL  VARIABLES   ********/
  1164. X     u_short  mode,            /* protection mode value          */
  1165. X          val,            /* temporary value              */
  1166. X          j,            /* loop and array index              */
  1167. X          scale;        /* scaling factor for current field   */
  1168. X
  1169. X   mode = 0;
  1170. X   val = 0;                /* digit value                  */
  1171. X   j = 0;                /* start with first group          */
  1172. X   scale = 0100;
  1173. X
  1174. X   while(j < (PROT_MAX - 1))
  1175. X   {
  1176. X      switch(*(str + j))
  1177. X      {
  1178. X     case('r'):
  1179. X        val += 4;
  1180. X        break;
  1181. X     case('-'):
  1182. X        break;
  1183. X     default:
  1184. X        return(FAILURE);
  1185. X      }
  1186. X
  1187. X      switch(*(str + j + 1))
  1188. X      {
  1189. X     case('w'):
  1190. X        val += 2;
  1191. X        break;
  1192. X     case('-'):
  1193. X        break;
  1194. X     default:
  1195. X        return(FAILURE);
  1196. X      }
  1197. X
  1198. X      /* add the mode for the current octal digit to the overall mode value */
  1199. X
  1200. X      mode = mode + (scale * val);
  1201. X      scale /= 010;            /* scale down for next digit          */
  1202. X      val = 0;                /* reset temporary digit value          */
  1203. X      j += 3;
  1204. X   }
  1205. X
  1206. X   /* now handle the x/s/S field of the first TWO digits in the mode string;
  1207. X    * we'll do the sticky bit last
  1208. X    */
  1209. X
  1210. X   switch(*(str + 2))
  1211. X   {
  1212. X      case('-'):
  1213. X     break;
  1214. X      case('x'):
  1215. X     mode += 0100;
  1216. X     break;
  1217. X      case('s'):
  1218. X     mode += 04100;
  1219. X     break;
  1220. X      case('S'):
  1221. X     mode += 04000;
  1222. X     break;
  1223. X      default:
  1224. X     return(FAILURE);
  1225. X   }
  1226. X
  1227. X   switch(*(str + 5))
  1228. X   {
  1229. X      case('-'):
  1230. X     break;
  1231. X      case('x'):
  1232. X     mode += 010;
  1233. X     break;
  1234. X      case('s'):
  1235. X     mode += 02010;
  1236. X     break;
  1237. X      case('S'):
  1238. X     mode += 02000;
  1239. X     break;
  1240. X      default:
  1241. X     return(FAILURE);
  1242. X   }
  1243. X
  1244. X   /* check for the last field */
  1245. X
  1246. X   switch(*(str + 8))
  1247. X   {
  1248. X      case('-'):
  1249. X     break;
  1250. X      case('x'):
  1251. X     mode++;
  1252. X     break;
  1253. X      case('t'):
  1254. X     mode += 01000;            /* sticky bit; only works for root    */
  1255. X     break;
  1256. X      default:
  1257. X     return(FAILURE);
  1258. X   }
  1259. X
  1260. X   if(*(str + 9))
  1261. X      return(FAILURE);            /* string too long              */
  1262. X
  1263. X   *new_val = mode;            /* ok here; set the return value      */
  1264. X   return(SUCCESS);
  1265. X
  1266. X}    /*** prot_str_to_val ***/
  1267. X
  1268. X/*******************************************************************************
  1269. X********************************************************************************
  1270. X
  1271. X  Function:    set_args
  1272. X
  1273. X  Purpose:    Set the original values for ent_factor and slot_width along
  1274. X        with initializing some of the other flags that provide infor-
  1275. X        mation about what run-time arguments were specified.
  1276. X
  1277. X  Global variables:
  1278. X
  1279. X    Name            Examine/Modify/Use/Read/Write
  1280. X    ----            -----------------------------
  1281. X    COLS
  1282. X
  1283. X  Return Codes:
  1284. X
  1285. X    Code            Reason
  1286. X    ----            ------
  1287. X    none
  1288. X
  1289. X********************************************************************************
  1290. X*******************************************************************************/
  1291. X
  1292. void set_args(args,slot_width,ent_factor)
  1293. X                    /*******   FORMAL  PARAMETERS   *******/
  1294. register ARG_DEF  *args;        /* run-time argument flags          */
  1295. X     short      *slot_width;        /* starting slot width              */
  1296. X     size_t      *ent_factor;        /* ent. size memory allocation factor */
  1297. X
  1298. X{    /*** set_args ***/
  1299. X
  1300. X   /* initialize the width to include the length of the filename that
  1301. X    * will be displayed and the spot to hold the cursor; also update
  1302. X    * the entry size factor for later
  1303. X    */
  1304. X
  1305. X   *slot_width = DISP_MAX;
  1306. X   *ent_factor = FUDGE_FACTOR;
  1307. X
  1308. X   /* we have to see what info should be included to get the
  1309. X    * slot width and the entry factor
  1310. X    */
  1311. X
  1312. X   if(args->date)
  1313. X      *slot_width = *slot_width + DATE_MAX + FIELD_GAP;
  1314. X
  1315. X   if(args->size)
  1316. X      *slot_width = *slot_width + SIZE_MAX + FIELD_GAP;
  1317. X
  1318. X   if(args->prot)
  1319. X      *slot_width = *slot_width + PROT_MAX + FIELD_GAP;
  1320. X
  1321. X   if(args->owner)
  1322. X      *slot_width = *slot_width + OWNER_MAX + FIELD_GAP;
  1323. X
  1324. X   if(args->group)
  1325. X      *slot_width = *slot_width + GROUP_MAX + FIELD_GAP;
  1326. X
  1327. X   if(args->text)
  1328. X   {
  1329. X      /* the user wants text descriptors */
  1330. X
  1331. X      *ent_factor = *ent_factor + TEXT_MAX + 1;
  1332. X      *slot_width = *slot_width + TEXT_MAX + FIELD_GAP;
  1333. X      /* now see if there is enough room to include the text descriptors on
  1334. X       * the screen
  1335. X       */
  1336. X
  1337. X      if(*slot_width > (COLS - 1))
  1338. X      {
  1339. X     args->text = SLOT_OVF;        /* they overflow the file slots          */
  1340. X     *slot_width = *slot_width - (TEXT_MAX + FIELD_GAP);
  1341. X      }
  1342. X   }
  1343. X
  1344. X   if(*slot_width == DISP_MAX)
  1345. X      args->def = 1;            /* just default info on screen          */
  1346. X   else
  1347. X      args->def = 0;            /* clear to be thorough.....          */
  1348. X
  1349. X   return;
  1350. X
  1351. X}    /*** set_args ***/
  1352. X
  1353. X/*******************************************************************************
  1354. X********************************************************************************
  1355. X
  1356. X  Function:    set_width
  1357. X
  1358. X  Purpose:    Set the slot width for the current directory based on whether
  1359. X        or not text descriptors will be included on the screen
  1360. X
  1361. X  Global variables:
  1362. X
  1363. X    Name            Examine/Modify/Use/Read/Write
  1364. X    ----            -----------------------------
  1365. X    none
  1366. X
  1367. X  Return Codes:
  1368. X
  1369. X    Code            Reason
  1370. X    ----            ------
  1371. X    none
  1372. X
  1373. X********************************************************************************
  1374. X*******************************************************************************/
  1375. X
  1376. void set_width(slot_width,text_flag)
  1377. X                    /*******   FORMAL  PARAMETERS   *******/
  1378. X     short      *slot_width,        /* current slot width              */
  1379. X          text_flag;        /* text descrips included for dir?    */
  1380. X
  1381. X{    /*** set_width ***/
  1382. X
  1383. X
  1384. X   /* should we at least TRY to get text descriptors on the screen? */
  1385. X
  1386. X   if(text_flag == DISPLAY_TEXT)
  1387. X   {
  1388. X      /* yes, they need to be displayed; increase the slot_width
  1389. X       * to accommodate them
  1390. X       */
  1391. X
  1392. X      *slot_width = *slot_width + TEXT_MAX + 1;
  1393. X   }
  1394. X
  1395. X   return;
  1396. X
  1397. X}    /*** set_width ***/
  1398. X
  1399. X/*******************************************************************************
  1400. X********************************************************************************
  1401. X
  1402. X  Function:    banystr
  1403. X
  1404. X  Purpose:    Determine if a finite-length character string contains
  1405. X        any characters from a second null-terminated character
  1406. X        string.
  1407. X
  1408. X  Global variables:
  1409. X
  1410. X    Name            Examine/Modify/Use/Read/Write
  1411. X    ----            -----------------------------
  1412. X    none
  1413. X
  1414. X  Return Codes:
  1415. X
  1416. X    Code            Reason
  1417. X    ----            ------
  1418. X     >=0            match was found; return code is the offset
  1419. X                into str1 where the character is found
  1420. X      -1            no common characters in the two strings
  1421. X
  1422. X********************************************************************************
  1423. X*******************************************************************************/
  1424. X
  1425. short banystr(str1,str2,length)
  1426. X                      /*******   FORMAL  PARAMETERS   *******/
  1427. register char      *str1,        /* string to search              */
  1428. X          *str2;        /* what to look for              */
  1429. X     short      length;        /* when to stop searching          */
  1430. X
  1431. X{    /*** banystr ***/
  1432. X                    /********   LOCAL  VARIABLES   ********/
  1433. register int      offset1,        /* offset into string str1          */
  1434. X          offset2;        /* offset into string str2          */
  1435. X
  1436. X
  1437. X   if(str1 == NULL || str2 == NULL || length <= 0)
  1438. X      return(-1);
  1439. X
  1440. X   if((*str1 == '\0') || (*str2 == '\0'))
  1441. X      return(-1);
  1442. X
  1443. X   offset1 = 0;
  1444. X
  1445. X   while(*(str1+offset1) != '\0' && length--)
  1446. X   {
  1447. X      offset2 = 0;
  1448. X      while(*(str2+offset2) != '\0')
  1449. X      {
  1450. X     if(*(str1+offset1) == *(str2+offset2))
  1451. X     {
  1452. X        return(offset1);        /* match found; return offset          */
  1453. X     }
  1454. X     ++offset2;
  1455. X      }
  1456. X      ++offset1;
  1457. X   }
  1458. X
  1459. X   return(-1);                /* no match; return -1              */
  1460. X
  1461. X}    /*** banystr ***/
  1462. X
  1463. X/*******************************************************************************
  1464. X********************************************************************************
  1465. X
  1466. X  Function:    set_type
  1467. X
  1468. X  Purpose:    Determine the type of a file and return it.
  1469. X
  1470. X  Global variables:
  1471. X
  1472. X    Name            Examine/Modify/Use/Read/Write
  1473. X    ----            -----------------------------
  1474. X    none
  1475. X
  1476. X  Return Codes:
  1477. X
  1478. X    Code            Reason
  1479. X    ----            ------
  1480. X    REGULAR            regular file
  1481. X    DIRECTORY        directory
  1482. X    CHARACTER        character-type special file
  1483. X    BLOCK            block special file
  1484. X    FIFO            FIFO (named pipe)
  1485. X    SOCKET            socket file
  1486. X    LINK            symbolic link
  1487. X
  1488. X********************************************************************************
  1489. X*******************************************************************************/
  1490. X
  1491. static u_char set_type(mode)
  1492. X                    /*******   FORMAL  PARAMETERS   *******/
  1493. X     u_short  mode;            /* protection mode to examine          */
  1494. X
  1495. X{    /*** set_type ***/
  1496. X
  1497. X   switch(mode & S_IFMT)
  1498. X   {
  1499. X#if !defined(SYSV) || defined(sun)
  1500. X      case(S_IFLNK):
  1501. X     return(LINK);
  1502. X#endif
  1503. X      case(S_IFREG):
  1504. X     return(REGULAR);
  1505. X      case(S_IFDIR):
  1506. X     return(DIRECTORY);
  1507. X      case(S_IFCHR):
  1508. X     return(CHARACTER);
  1509. X      case(S_IFBLK):
  1510. X     return(BLOCK);
  1511. X#if !defined(SYSV) || defined(sun)
  1512. X      case(S_IFSOCK):
  1513. X     return(SOCKET);
  1514. X#endif
  1515. X      case(S_IFIFO):
  1516. X     return(FIFO);
  1517. X      default:
  1518. X     break;
  1519. X    }
  1520. X
  1521. X   return(REGULAR);            /* default is regular type          */
  1522. X
  1523. X}    /*** set_type ***/
  1524. X
  1525. X/*******************************************************************************
  1526. X********************************************************************************
  1527. X
  1528. X  Function:    set_date
  1529. X
  1530. X  Purpose:    Create a date string for a file.
  1531. X
  1532. X  Global variables:
  1533. X
  1534. X    Name            Examine/Modify/Use/Read/Write
  1535. X    ----            -----------------------------
  1536. X    curr_year           X
  1537. X
  1538. X  Return Codes:
  1539. X
  1540. X    Code            Reason
  1541. X    ----            ------
  1542. X    date_buf        buffer where date string is stored
  1543. X
  1544. X********************************************************************************
  1545. X*******************************************************************************/
  1546. X
  1547. char *set_date(time_val)
  1548. X                    /*******   FORMAL  PARAMETERS   *******/
  1549. X     time_t      time_val;        /* binary time value              */
  1550. X
  1551. X{    /*** set_date ***/
  1552. X                    /********   LOCAL  VARIABLES   ********/
  1553. struct     tm      *time_str;        /* time structure              */
  1554. static     char      date_buf[DATE_MAX+1];
  1555. static     char      *month[] =
  1556. X{"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
  1557. X
  1558. X   time_str = localtime(&time_val);
  1559. X
  1560. X   if(time_str->tm_year == curr_year)
  1561. X      sprintf(date_buf,"%3s %2d %2d:%1d%1d",month[time_str->tm_mon],
  1562. X          time_str->tm_mday,time_str->tm_hour,time_str->tm_min/10,
  1563. X          time_str->tm_min%10);
  1564. X   else
  1565. X      sprintf(date_buf,"%3s %2d  %4d",month[time_str->tm_mon],
  1566. X          time_str->tm_mday,time_str->tm_year + 1900);
  1567. X
  1568. X   return(date_buf);
  1569. X
  1570. X}    /*** set_date ***/
  1571. X
  1572. X/*******************************************************************************
  1573. X********************************************************************************
  1574. X
  1575. X  Function:    padcpy
  1576. X
  1577. X  Purpose:    Copy a counted string, padding with spaces.
  1578. X
  1579. X  Global variables:
  1580. X
  1581. X    Name            Examine/Modify/Use/Read/Write
  1582. X    ----            -----------------------------
  1583. X    none
  1584. X
  1585. X  Return Codes:
  1586. X
  1587. X    Code            Reason
  1588. X    ----            ------
  1589. X    date_buf        buffer where date string is stored
  1590. X
  1591. X********************************************************************************
  1592. X*******************************************************************************/
  1593. X
  1594. char *padcpy(dest,source,length)
  1595. X                    /********   LOCAL  VARIABLES   ********/
  1596. X     char      *dest,        /* destination string              */
  1597. X          *source;        /* source string              */
  1598. X     int      length;        /* length that destination should be  */
  1599. X
  1600. X{    /*** padcpy ***/
  1601. X
  1602. X   if(source != NULL && *source != '\0')
  1603. X   {
  1604. X      while(*source && length--)    /* copy it                  */
  1605. X     *dest++ = *source++;
  1606. X   }
  1607. X
  1608. X   while(length-- > 0)            /* pad it                  */
  1609. X      *dest++ = ' ';
  1610. X
  1611. X   *dest = '\0';            /* make it a string              */
  1612. X   return(dest);
  1613. X
  1614. X}    /*** padcpy ***/
  1615. X
  1616. X/*******************************************************************************
  1617. X********************************************************************************
  1618. X
  1619. X  Function:    add_filetype
  1620. X
  1621. X  Purpose:    Set the filetype in an integer file mode.
  1622. X
  1623. X  Global variables:
  1624. X
  1625. X    Name            Examine/Modify/Use/Read/Write
  1626. X    ----            -----------------------------
  1627. X    none
  1628. X
  1629. X  Return Codes:
  1630. X
  1631. X    Code            Reason
  1632. X    ----            ------
  1633. X    prot            new protection value
  1634. X
  1635. X********************************************************************************
  1636. X*******************************************************************************/
  1637. X
  1638. u_short add_filetype(type,prot)
  1639. X                    /*******   FORMAL  PARAMETERS   *******/
  1640. X     u_char      type;            /* type of file                  */
  1641. X     u_short  prot;            /* protection mode to work with          */
  1642. X
  1643. X{    /*** add_filetype ***/
  1644. X
  1645. X
  1646. X   switch(type)
  1647. X   {
  1648. X      case(REGULAR):
  1649. X     prot |= S_IFREG;
  1650. X     break;
  1651. X      case(DIRECTORY):
  1652. X     prot |= S_IFDIR;
  1653. X     break;
  1654. X      case(CHARACTER):
  1655. X     prot |= S_IFCHR;
  1656. X     break;
  1657. X      case(BLOCK):
  1658. X     prot |= S_IFBLK;
  1659. X     break;
  1660. X      case(FIFO):
  1661. X     prot |= S_IFIFO;
  1662. X     break;
  1663. X#if !defined(SYSV) || defined(sun)
  1664. X      case(SOCKET):
  1665. X     prot |= S_IFSOCK;
  1666. X     break;
  1667. X      case(LINK):
  1668. X     prot |= S_IFLNK;
  1669. X     break;
  1670. X#endif
  1671. X      default:
  1672. X     prot |= S_IFREG;
  1673. X     break;
  1674. X   }
  1675. X
  1676. X   return(prot);
  1677. X
  1678. X}    /*** add_filetype ***/
  1679. X
  1680. X/*******************************************************************************
  1681. X********************************************************************************
  1682. X
  1683. X  Function:    spawn
  1684. X
  1685. X  Purpose:    Fork off a process to let the user return to the shell.
  1686. X
  1687. X  Global variables:
  1688. X
  1689. X    Name            Examine/Modify/Use/Read/Write
  1690. X    ----            -----------------------------
  1691. X    none
  1692. X
  1693. X  Return Codes:
  1694. X
  1695. X    Code            Reason
  1696. X    ----            ------
  1697. X    SUCCESS
  1698. X    FAILURE
  1699. X
  1700. X********************************************************************************
  1701. X*******************************************************************************/
  1702. X
  1703. int spawn()
  1704. X
  1705. X{    /*** spawn ***/
  1706. X                    /********   LOCAL  VARIABLES   ********/
  1707. X     char      *tptr,        /* temporary pointer              */
  1708. X          *shell;        /* pointer to the user's shell          */
  1709. X     int      child,        /* pid of child process              */
  1710. X          i;            /* loop and return value          */
  1711. X#if !defined(SYSV) || defined(sun)
  1712. union     wait      status;
  1713. X#else
  1714. X     int      status;
  1715. X#endif
  1716. X
  1717. X
  1718. X   shell = getenv("SHELL");        /* get what shell to use          */
  1719. X
  1720. X   if(shell == NULL || *shell == '\0')
  1721. X      shell = DEFAULT_SHELL;        /* user didn't have a SHELL variable  */
  1722. X
  1723. X   tptr = strrchr(shell,'/');        /* find last level of shell name      */
  1724. X
  1725. X   if(tptr == NULL)
  1726. X      tptr = shell;
  1727. X   else
  1728. X      tptr++;
  1729. X
  1730. X   if((child = vfork()) == 0)
  1731. X   {
  1732. X      /* we're in the child */
  1733. X
  1734. X      endwin();                /* make sure tty is reset          */
  1735. X      execlp(shell,tptr,NULL);        /* no return from this              */
  1736. X      return(FAILURE);            /* failure if we get here          */
  1737. X   }
  1738. X   else if(child > 0)
  1739. X   {
  1740. X      /* we're in the parent; wait for the child to finish */
  1741. X
  1742. X      while(((i = wait(&status)) != child) && i > 0)
  1743. X     ;
  1744. X   }
  1745. X   else
  1746. X      return(FAILURE);            /* can't fork                  */
  1747. X
  1748. X   return(SUCCESS);
  1749. X
  1750. X}    /*** spawn ***/
  1751. X
  1752. X/*******************************************************************************
  1753. X********************************************************************************
  1754. X
  1755. X  Function:    check_nlen
  1756. X
  1757. X  Purpose:    Check if a filename (as displayed) would be longer than
  1758. X        DISP_MAX.  This info is useful in make_slot() when we are
  1759. X        deciding what has to be tagged.
  1760. X
  1761. X  Global variables:
  1762. X
  1763. X    Name            Examine/Modify/Use/Read/Write
  1764. X    ----            -----------------------------
  1765. X    none
  1766. X
  1767. X  Return Codes:
  1768. X
  1769. X    Code            Reason
  1770. X    ----            ------
  1771. X    count            displayed length of filename
  1772. X
  1773. X********************************************************************************
  1774. X*******************************************************************************/
  1775. X
  1776. static u_short check_nlen(filename)
  1777. X                    /*******   FORMAL  PARAMETERS   *******/
  1778. register char      *filename;        /* filename to be checked          */
  1779. X
  1780. X{    /*** check_nlen ***/
  1781. X                    /********   LOCAL  VARIABLES   ********/
  1782. register u_short  count;        /* length of displayed filename          */
  1783. X
  1784. X
  1785. X   count = 0;
  1786. X
  1787. X   while(*filename)
  1788. X   {
  1789. X      if(!iscntrl(*filename))
  1790. X     count++;
  1791. X      else
  1792. X     count += 2;
  1793. X
  1794. X      ++filename;
  1795. X   }
  1796. X
  1797. X   return(count);
  1798. X
  1799. X}    /*** check_nlen ***/
  1800. X
  1801. X/*******************************************************************************
  1802. X********************************************************************************
  1803. X
  1804. X  Function:    strtcpy
  1805. X
  1806. X  Purpose:    Copy one string to another, translating control characters to
  1807. X        a two-character pair of ^ and the printable control character.
  1808. X
  1809. X  Global variables:
  1810. X
  1811. X    Name            Examine/Modify/Use/Read/Write
  1812. X    ----            -----------------------------
  1813. X    none
  1814. X
  1815. X  Return Codes:
  1816. X
  1817. X    Code            Reason
  1818. X    ----            ------
  1819. X    count            displayed length of filename
  1820. X
  1821. X********************************************************************************
  1822. X*******************************************************************************/
  1823. X
  1824. int strtcpy(dest,source)
  1825. X                    /*******   FORMAL  PARAMETERS   *******/
  1826. register char      *dest,        /* destination string              */
  1827. X          *source;        /* source string              */
  1828. X
  1829. X{    /*** strtcpy ***/
  1830. X                    /********   LOCAL  VARIABLES   ********/
  1831. register int      length;        /* length of resulting string          */
  1832. X
  1833. X
  1834. X   length = 0;
  1835. X
  1836. X   while(*source)
  1837. X   {
  1838. X      if(iscntrl(*source))
  1839. X      {
  1840. X     *dest++ = '^';
  1841. X     *dest++ = *source++ + '@';    /* make it printable              */
  1842. X     length += 2;
  1843. X      }
  1844. X      else
  1845. X      {
  1846. X     *dest++ = *source++;
  1847. X     ++length;
  1848. X      }
  1849. X   }
  1850. X
  1851. X   *dest = '\0';            /* make it a string              */
  1852. X   return(length);
  1853. X
  1854. X}    /*** strtcpy ***/
  1855. X
  1856. X/*******************************************************************************
  1857. X********************************************************************************
  1858. X
  1859. X  Function:    get_filemarks
  1860. X
  1861. X  Purpose:    Recreate the displayed names for all of the files in the
  1862. X        current directory so that they include the filemarks.  This
  1863. X        is normally only done after the filemarks are selected from
  1864. X        the options menu.
  1865. X
  1866. X  Global variables:
  1867. X
  1868. X    Name            Examine/Modify/Use/Read/Write
  1869. X    ----            -----------------------------
  1870. X    none
  1871. X
  1872. X  Return Codes:
  1873. X
  1874. X    Code            Reason
  1875. X    ----            ------
  1876. X    none
  1877. X
  1878. X********************************************************************************
  1879. X*******************************************************************************/
  1880. X
  1881. void get_filemarks(dirptr,num_file)
  1882. X                    /*******   FORMAL  PARAMETERS   *******/
  1883. register ENT_DEF  *dirptr;        /* pointer to directory information   */
  1884. register short      num_file;        /* number of files in directory          */
  1885. X
  1886. X{    /*** get_filemarks ***/
  1887. X
  1888. X   while(num_file-- > 0)
  1889. X   {
  1890. X      strcpy(dirptr->scr_name,get_name(dirptr->filename,&dirptr->name_len),
  1891. X         dirptr->prot,dirptr->type);
  1892. X      dirptr++;
  1893. X   }
  1894. X
  1895. X   return;
  1896. X
  1897. X}    /*** get_filemarks ***/
  1898. X
  1899. X/*******************************************************************************
  1900. X********************************************************************************
  1901. X
  1902. X  Function:    get_name
  1903. X
  1904. X  Purpose:    Create the filename that will be displayed in a slot, including
  1905. X        translating non-printable characters.
  1906. X
  1907. X  Global variables:
  1908. X
  1909. X    Name            Examine/Modify/Use/Read/Write
  1910. X    ----            -----------------------------
  1911. X    args.filemarks           X
  1912. X
  1913. X  Return Codes:
  1914. X
  1915. X    Code            Reason
  1916. X    ----            ------
  1917. X    retptr            pointer to displayed filename string
  1918. X
  1919. X********************************************************************************
  1920. X*******************************************************************************/
  1921. X
  1922. static char *get_name(filename,length,prot,type)
  1923. X                    /*******   FORMAL  PARAMETERS   *******/
  1924. X     char      *filename;        /* original filename              */
  1925. X     u_short  *length,        /* length of filename minus padding   */
  1926. X          prot;            /* integer protection value          */
  1927. X     u_char      type;            /* file type                  */
  1928. X
  1929. X{    /*** get_name ***/
  1930. X                    /********   LOCAL  VARIABLES   ********/
  1931. register char      *tptr;        /* temporary character pointer          */
  1932. register u_short  i;            /* loop and array index              */
  1933. static     char      newname[DISP_MAX+1];    /* where to store translated name     */
  1934. X
  1935. X
  1936. X   i = 0;
  1937. X   tptr = newname;
  1938. X
  1939. X   while((i < DNAME_MAX) && (*filename != '\0'))
  1940. X   {
  1941. X      if(*filename >= ' ')
  1942. X      {
  1943. X     *tptr = *filename;
  1944. X     tptr++;
  1945. X     filename++;
  1946. X     ++i;
  1947. X      }
  1948. X      else
  1949. X      {
  1950. X     *tptr++ = '^';            /* non-printable; translate it          */
  1951. X     ++i;
  1952. X
  1953. X     if(i < DNAME_MAX)
  1954. X     {
  1955. X        *tptr = *filename + '@';
  1956. X        ++i;
  1957. X        tptr++;
  1958. X     }
  1959. X
  1960. X     filename++;
  1961. X      }
  1962. X   }
  1963. X
  1964. X   /* pad the name with spaces */
  1965. X
  1966. X   if(args.filemarks)
  1967. X      *tptr++ = filetype_char(prot,type);
  1968. X   else
  1969. X      *tptr++ = ' ';
  1970. X
  1971. X   *length = ++i;            /* count the filemark char          */
  1972. X
  1973. X   while(i++ < DISP_MAX)
  1974. X      *tptr++ = ' ';
  1975. X
  1976. X   *tptr = '\0';            /* make sure it's a string          */
  1977. X   return(newname);
  1978. X
  1979. X}    /*** get_name ***/
  1980. X
  1981. X/*******************************************************************************
  1982. X********************************************************************************
  1983. X
  1984. X  Function:    filetype_char
  1985. X
  1986. X  Purpose:    Determine what character should be appended to the filename
  1987. X        for the -F option.
  1988. X
  1989. X  Global variables:
  1990. X
  1991. X    Name            Examine/Modify/Use/Read/Write
  1992. X    ----            -----------------------------
  1993. X    none
  1994. X
  1995. X  Return Codes:
  1996. X
  1997. X    Code            Reason
  1998. X    ----            ------
  1999. X    retval            filetype character
  2000. X
  2001. X********************************************************************************
  2002. X*******************************************************************************/
  2003. X
  2004. u_char filetype_char(prot,type)
  2005. X                    /*******   FORMAL  PARAMETERS   *******/
  2006. X     u_short  prot;            /* file protection word              */
  2007. X     u_char      type;            /* type of file                  */
  2008. X
  2009. X{    /*** filetype_char ***/
  2010. X                    /********   LOCAL  VARIABLES   ********/
  2011. X     u_char      retval;        /* file type char (for -F)          */
  2012. X
  2013. X
  2014. X   switch(type)
  2015. X   {
  2016. X      case(DIRECTORY):
  2017. X
  2018. X     retval = '/';
  2019. X     break;
  2020. X
  2021. X      case(SOCKET):
  2022. X
  2023. X     retval = '=';
  2024. X     break;
  2025. X
  2026. X#if !defined(SYSV) || defined(sun)
  2027. X      case(LINK):
  2028. X
  2029. X     retval = '@';
  2030. X     break;
  2031. X#endif
  2032. X
  2033. X      case(REGULAR):
  2034. X
  2035. X     /* determine if the file is executable */
  2036. X
  2037. X     if(prot & (S_IEXEC | (S_IEXEC >> 3) | (S_IEXEC >> 6)))
  2038. X        retval = '*';
  2039. X     else
  2040. X        retval = ' ';
  2041. X
  2042. X     break;
  2043. X
  2044. X      default:
  2045. X
  2046. X     retval = ' ';
  2047. X     break;
  2048. X   }
  2049. X
  2050. X   return(retval);
  2051. X
  2052. X}    /*** filetype_char ****/
  2053. X
  2054. X/*******************************************************************************
  2055. X********************************************************************************
  2056. X
  2057. X  Function:    squeeze_str
  2058. X
  2059. X  Purpose:    Squeeze the whitespace characters out of a string
  2060. X
  2061. X  Global variables:
  2062. X
  2063. X    Name            Examine/Modify/Use/Read/Write
  2064. X    ----            -----------------------------
  2065. X    none
  2066. X
  2067. X  Return Codes:
  2068. X
  2069. X    Code            Reason
  2070. X    ----            ------
  2071. X    none
  2072. X
  2073. X********************************************************************************
  2074. X*******************************************************************************/
  2075. X
  2076. void squeeze_str(str)
  2077. X                    /*******   FORMAL  PARAMETERS   *******/
  2078. register char      *str;            /* string to be squeezed          */
  2079. X
  2080. X{    /*** squeeze_str ***/
  2081. X                    /********   LOCAL  VARIABLES   ********/
  2082. register char      *ptr;            /* temporary pointer              */
  2083. X
  2084. X
  2085. X   ptr = str;
  2086. X
  2087. X   while(*ptr)
  2088. X   {
  2089. X      if(!isspace(*ptr))
  2090. X     *str++ = *ptr++;
  2091. X      else
  2092. X     ptr++;
  2093. X   }
  2094. X
  2095. X   *str = '\0';                /* make sure it's a string          */
  2096. X   return;
  2097. X
  2098. X}    /*** squeeze_str ***/
  2099. X
  2100. X/*******************************************************************************
  2101. X********************************************************************************
  2102. X
  2103. X  Function:    follow_link
  2104. X
  2105. X  Purpose:    Given a filename that is a symbolic link, try to find out what
  2106. X        it points to.
  2107. X
  2108. X  Global variables:
  2109. X
  2110. X    Name            Examine/Modify/Use/Read/Write
  2111. X    ----            -----------------------------
  2112. X    none
  2113. X
  2114. X  Return Codes:
  2115. X
  2116. X    Code            Reason
  2117. X    ----            ------
  2118. X    REGULAR
  2119. X    DIRECTORY
  2120. X    CHARACTER
  2121. X    BLOCK
  2122. X    LINK
  2123. X    SOCKET
  2124. X
  2125. X********************************************************************************
  2126. X*******************************************************************************/
  2127. X
  2128. int follow_link(linkname)
  2129. X                    /*******   FORMAL  PARAMETERS   *******/
  2130. X     char      *linkname;        /* link to follow              */
  2131. X
  2132. X{    /*** follow_link ***/
  2133. X                    /********   LOCAL  VARIABLES   ********/
  2134. struct     stat      statbuf;        /* for stat'ing the file          */
  2135. X
  2136. X
  2137. X   if(stat(linkname,&statbuf) == -1)
  2138. X      return(FAILURE);
  2139. X
  2140. X   switch(statbuf.st_mode & S_IFMT)
  2141. X   {
  2142. X      case(S_IFREG):
  2143. X     return(REGULAR);
  2144. X      case(S_IFDIR):
  2145. X     return(DIRECTORY);
  2146. X      case(S_IFCHR):
  2147. X     return(CHARACTER);
  2148. X      case(S_IFBLK):
  2149. X     return(BLOCK);
  2150. X#if !defined(SYSV) || defined(sun)
  2151. X      case(S_IFLNK):
  2152. X     return(LINK);
  2153. X      case(S_IFSOCK):
  2154. X     return(SOCKET);
  2155. X#endif
  2156. X      default:
  2157. X     break;
  2158. X   }
  2159. X
  2160. X   return(REGULAR);
  2161. X
  2162. X}    /*** follow_link ***/
  2163. X
  2164. X/*******************************************************************************
  2165. X********************************************************************************
  2166. X
  2167. X  Function:    get_bnum
  2168. X
  2169. X  Purpose:    Get the number of blocks that a file occupies and return it.
  2170. X
  2171. X  Global variables:
  2172. X
  2173. X    Name            Examine/Modify/Use/Read/Write
  2174. X    ----            -----------------------------
  2175. X    none
  2176. X
  2177. X  Return Codes:
  2178. X
  2179. X    Code            Reason
  2180. X    ----            ------
  2181. X    kbytes(...)        number of blocks the file occupies
  2182. X
  2183. X********************************************************************************
  2184. X*******************************************************************************/
  2185. X
  2186. long get_bnum(filename)
  2187. X                    /*******   FORMAL  PARAMETERS   *******/
  2188. X     char      *filename;        /* file to be examined              */
  2189. X
  2190. X{    /*** get_bnum ***/
  2191. X                    /********   LOCAL  VARIABLES   ********/
  2192. struct     stat      statbuf;        /* for doing a stat              */
  2193. X
  2194. X
  2195. X   if(stat(filename,&statbuf) != 0)
  2196. X      return(0L);
  2197. X
  2198. X#if !defined(SYSV) || defined(sun)
  2199. X   return((long) statbuf.st_blocks);
  2200. X#else
  2201. X   return((long) statbuf.st_size);
  2202. X#endif
  2203. X
  2204. X}    /*** get_bnum ***/
  2205. X
  2206. X/*******************************************************************************
  2207. X********************************************************************************
  2208. X
  2209. X  Function:    cont_after_stop
  2210. X
  2211. X  Purpose:    Signal hander called when restarting after being suspended
  2212. X
  2213. X  Global variables:
  2214. X
  2215. X    Name            Examine/Modify/Use/Read/Write
  2216. X    ----            -----------------------------
  2217. X    main_win                X
  2218. X    spec_win                X
  2219. X    stat_win                X
  2220. X
  2221. X  Return Codes:
  2222. X
  2223. X    Code            Reason
  2224. X    ----            ------
  2225. X    none
  2226. X
  2227. X********************************************************************************
  2228. X*******************************************************************************/
  2229. X
  2230. void cont_after_stop()
  2231. X
  2232. X{    /*** cont_after_stop ***/
  2233. X
  2234. X   /* redraw the screen after resuming */
  2235. X
  2236. X   touchwin(spec_win);
  2237. X   touchwin(main_win);
  2238. X   touchwin(stat_win);
  2239. X   wrefresh(spec_win);
  2240. X   wrefresh(main_win);
  2241. X   wrefresh(stat_win);
  2242. X   return;
  2243. X
  2244. X}    /*** cont_after_stop ***/
  2245. X
  2246. X/*******************************************************************************
  2247. X********************************************************************************
  2248. X
  2249. X  Function:    cat
  2250. X
  2251. X  Purpose:    Concatenate strings into one string.
  2252. X
  2253. X  Global variables:
  2254. X
  2255. X    Name            Examine/Modify/Use/Read/Write
  2256. X    ----            -----------------------------
  2257. X    none
  2258. X
  2259. X  Return Codes:
  2260. X
  2261. X    Code            Reason
  2262. X    ----            ------
  2263. X    retval            pointer to destination string
  2264. X    NULL            null string pointer; returned when
  2265. X                no arguments are passed
  2266. X
  2267. X  Termination Codes:
  2268. X
  2269. X    Code            Reason
  2270. X    ----            ------
  2271. X    none
  2272. X
  2273. X  Description of Linkage:
  2274. X
  2275. X    char    *rc,
  2276. X        *cat();
  2277. X
  2278. X    rc = cat(num_args,dest,source1,source2,...sourcen);
  2279. X
  2280. X    where dest is a pointer to a character string allocated by
  2281. X    the caller and is large enough to hold the resulting string
  2282. X    and source1, source2,...sourcen are pointers to character
  2283. X    strings to be concatenated.
  2284. X
  2285. X********************************************************************************
  2286. X*******************************************************************************/
  2287. X
  2288. char *cat(va_alist)
  2289. X                    /*******   FORMAL  PARAMETERS   *******/
  2290. X     va_dcl                /* variable-length parameter list     */
  2291. X
  2292. X{    /*** cat ***/
  2293. X                    /********   LOCAL  VARIABLES   ********/
  2294. static     char      *dest,        /* pointer to destination string      */
  2295. X          *source;        /* pointer to current source string   */
  2296. static     char      *retval;        /* to save pointer to destination     */
  2297. static     int      count;        /* number of arguments passed          */
  2298. static     va_list  incrmtr;        /* argument list incrementor          */
  2299. X
  2300. X
  2301. X   va_start(incrmtr);            /* begin everything....              */
  2302. X
  2303. X   count = va_arg(incrmtr,int);        /* get number of arguments          */
  2304. X
  2305. X   if(count <= 1)            /* enough arguments?              */
  2306. X      return(NULL);            /* nope, get out of here...          */
  2307. X
  2308. X   dest = va_arg(incrmtr,char*);    /* get the destination pointer          */
  2309. X   retval = dest;            /* save pointer to destination          */
  2310. X
  2311. X   --count;                /* subtract for first argument          */
  2312. X
  2313. X   while(count > 0)            /* process all of the source strings  */
  2314. X   {
  2315. X      source = va_arg(incrmtr,char*);    /* get the next argument          */
  2316. X      while(*dest++ = *source++)    /* cat the source to the destination  */
  2317. X     ;
  2318. X
  2319. X      dest--;                /* back over the null character          */
  2320. X      count--;
  2321. X   }
  2322. X
  2323. X   *dest = '\0';            /* terminate the destination          */
  2324. X   va_end(incrmtr);            /* end varargs session              */
  2325. X
  2326. X   return(retval);            /* return pointer to destination      */
  2327. X
  2328. X}    /*** cat ***/
  2329. X
  2330. X/*******************************************************************************
  2331. X********************************************************************************
  2332. X
  2333. X  Function:    strindex
  2334. X
  2335. X  Purpose:    Return the position of one string in another.
  2336. X
  2337. X  Global variables:
  2338. X
  2339. X    Name            Examine/Modify/Use/Read/Write
  2340. X    ----            -----------------------------
  2341. X    none
  2342. X
  2343. X  Return Codes:
  2344. X
  2345. X    Code            Reason
  2346. X    ----            ------
  2347. X     -1            key not found in str or key is a null
  2348. X                pointer or str is a null pointer
  2349. X    offset            offset into str where key is located
  2350. X
  2351. X  Termination Codes:
  2352. X
  2353. X    Code            Reason
  2354. X    ----            ------
  2355. X    none
  2356. X
  2357. X   Description of Linkage:
  2358. X
  2359. X    int  strindex();
  2360. X    rc = strindex(str,key);
  2361. X
  2362. X********************************************************************************
  2363. X*******************************************************************************/
  2364. X
  2365. int strindex(str,key)
  2366. X                    /*******   FORMAL  PARAMETERS   *******/
  2367. register char      *str,            /* string to be searched          */
  2368. X          *key;            /* string to be searched for          */
  2369. X
  2370. X{    /*** strindex ***/
  2371. X                    /********   LOCAL  VARIABLES   ********/
  2372. register int      i,            /* primary pointer to str          */
  2373. X          j,            /* secondary pointer to str for com-  */
  2374. X                    /* parison                  */
  2375. X          k;            /* pointer to key for comparison      */
  2376. X
  2377. X
  2378. X   if(str == NULL || key == NULL || *str == '\0' || *key == '\0')
  2379. X      return(-1);
  2380. X
  2381. X   i = 0;
  2382. X   while(*(str+i) != '\0')
  2383. X   {
  2384. X      j = i;
  2385. X      k = 0;
  2386. X
  2387. X      /* look for a match */
  2388. X
  2389. X      while((*(str+j) == *(key+k)) && (*(str+j) != '\0') && (*(key+k) != '\0'))
  2390. X      {
  2391. X     ++j;
  2392. X     ++k;
  2393. X      }
  2394. X
  2395. X      if(*(key+k) == '\0')
  2396. X     return(i);            /* key was found              */
  2397. X      else if(*(str+j) == '\0')
  2398. X     return(-1);            /* key was not found              */
  2399. X
  2400. X      ++i;                /* not sure yet; keep trying...          */
  2401. X   }
  2402. X
  2403. X   /* if we get to here, the key was not found */
  2404. X
  2405. X   return(-1);
  2406. X
  2407. X}    /*** strindex ***/
  2408. X
  2409. X/*******************************************************************************
  2410. X********************************************************************************
  2411. X
  2412. X  Function:    rename
  2413. X
  2414. X  Purpose:    Fake a rename function for System V machines
  2415. X
  2416. X  Global variables:
  2417. X
  2418. X    Name            Examine/Modify/Use/Read/Write
  2419. X    ----            -----------------------------
  2420. X    none
  2421. X
  2422. X  Return Codes:
  2423. X
  2424. X    Code            Reason
  2425. X    ----            ------
  2426. X     -1            key not found in str or key is a null
  2427. X                pointer or str is a null pointer
  2428. X    offset            offset into str where key is located
  2429. X
  2430. X  Termination Codes:
  2431. X
  2432. X    Code            Reason
  2433. X    ----            ------
  2434. X    none
  2435. X
  2436. X********************************************************************************
  2437. X*******************************************************************************/
  2438. X
  2439. X#if defined(SYSV) && !defined(sun)
  2440. X
  2441. int rename(source,dest)
  2442. X                    /*******   FORMAL  PARAMETERS   *******/
  2443. X     char      *source,        /* file to be renamed              */          *dest;        /* what to call it              */
  2444. X
  2445. X{    /*** rename ***/
  2446. X
  2447. X   if(link(source,dest))
  2448. X      return(-1);
  2449. X
  2450. X   if(unlink(source))
  2451. X      return(-1);
  2452. X
  2453. X   return(0);
  2454. X
  2455. X}    /*** rename ***/
  2456. X
  2457. X#endif
  2458. END_OF_FILE
  2459. if test 62428 -ne `wc -c <'misc.c.orig'`; then
  2460.     echo shar: \"'misc.c.orig'\" unpacked with wrong size!
  2461. fi
  2462. # end of 'misc.c.orig'
  2463. fi
  2464. echo shar: End of archive 6 \(of 7\).
  2465. cp /dev/null ark6isdone
  2466. MISSING=""
  2467. for I in 1 2 3 4 5 6 7 ; do
  2468.     if test ! -f ark${I}isdone ; then
  2469.     MISSING="${MISSING} ${I}"
  2470.     fi
  2471. done
  2472. if test "${MISSING}" = "" ; then
  2473.     echo You have unpacked all 7 archives.
  2474.     rm -f ark[1-9]isdone
  2475. else
  2476.     echo You still need to unpack the following archives:
  2477.     echo "        " ${MISSING}
  2478. fi
  2479. ##  End of shell archive.
  2480. exit 0
  2481.