Home | History | Annotate | Download | only in ss
      1 /*
      2  * Copyright 1987, 1988 by MIT Student Information Processing Board
      3  *
      4  * Permission to use, copy, modify, and distribute this software and
      5  * its documentation for any purpose is hereby granted, provided that
      6  * the names of M.I.T. and the M.I.T. S.I.P.B. not be used in
      7  * advertising or publicity pertaining to distribution of the software
      8  * without specific, written prior permission.  M.I.T. and the
      9  * M.I.T. S.I.P.B. make no representations about the suitability of
     10  * this software for any purpose.  It is provided "as is" without
     11  * express or implied warranty.
     12  */
     13 
     14 #ifdef HAVE_UNISTD_H
     15 #include <unistd.h>
     16 #endif
     17 #ifdef HAVE_STDLIB_H
     18 #include <stdlib.h>
     19 #endif
     20 #ifdef HAVE_ERRNO_H
     21 #include <errno.h>
     22 #else
     23 extern int errno;
     24 #endif
     25 #include <fcntl.h>
     26 #include <sys/param.h>
     27 #include <sys/types.h>
     28 #include <sys/file.h>
     29 #ifdef NEED_SYS_FCNTL_H
     30 /* just for O_* */
     31 #include <sys/fcntl.h>
     32 #endif
     33 #ifdef HAVE_SYS_WAIT_H
     34 #include <sys/wait.h>
     35 #endif
     36 #include "ss_internal.h"
     37 
     38 void ss_help(int argc, char const * const *argv, int sci_idx, pointer info_ptr)
     39 {
     40     char *buffer;
     41     char const *request_name;
     42     int code;
     43     int fd, child;
     44     register int idx;
     45     register ss_data *info;
     46 
     47     request_name = ss_current_request(sci_idx, &code);
     48     if (code != 0) {
     49 	ss_perror(sci_idx, code, "");
     50 	return;		/* no ss_abort_line, if invalid invocation */
     51     }
     52     if (argc == 1) {
     53 	ss_list_requests(argc, argv, sci_idx, info_ptr);
     54 	return;
     55     }
     56     else if (argc != 2) {
     57 	/* should do something better than this */
     58 	buffer = malloc(80+2*strlen(request_name));
     59 	if (!buffer) {
     60 		ss_perror(sci_idx, 0,
     61 			  "couldn't allocate memory to print usage message");
     62 		return;
     63 	}
     64 	sprintf(buffer, "usage:\n\t%s [topic|command]\nor\t%s\n",
     65 		request_name, request_name);
     66 	ss_perror(sci_idx, 0, buffer);
     67 	free(buffer);
     68 	return;
     69     }
     70     info = ss_info(sci_idx);
     71     if (info->info_dirs == (char **)NULL) {
     72 	ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
     73 	return;
     74     }
     75     if (info->info_dirs[0] == (char *)NULL) {
     76 	ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
     77 	return;
     78     }
     79     for (fd = -1, idx = 0; info->info_dirs[idx] != (char *)NULL; idx++) {
     80         buffer = malloc(strlen (info->info_dirs[idx]) + 1 +
     81 			strlen (argv[1]) + 6);
     82 	if (!buffer) {
     83 	    ss_perror(sci_idx, 0,
     84 		      "couldn't allocate memory for help filename");
     85 	    return;
     86 	}
     87 	(void) strcpy(buffer, info->info_dirs[idx]);
     88 	(void) strcat(buffer, "/");
     89 	(void) strcat(buffer, argv[1]);
     90 	(void) strcat(buffer, ".info");
     91 	fd = open(buffer, O_RDONLY);
     92 	free(buffer);
     93 	if (fd >= 0)
     94 	    break;
     95     }
     96     if (fd < 0) {
     97 #define MSG "No info found for "
     98         char *buf = malloc(strlen (MSG) + strlen (argv[1]) + 1);
     99 	strcpy(buf, MSG);
    100 	strcat(buf, argv[1]);
    101 	ss_perror(sci_idx, 0, buf);
    102 	free(buf);
    103 	return;
    104     }
    105     switch (child = fork()) {
    106     case -1:
    107 	ss_perror(sci_idx, errno, "Can't fork for pager");
    108 	(void) close(fd);
    109 	return;
    110     case 0:
    111 	(void) dup2(fd, 0); /* put file on stdin */
    112 	ss_page_stdin();
    113     default:
    114 	(void) close(fd); /* what can we do if it fails? */
    115 	while (wait(NULL) != child) {
    116 	    /* do nothing if wrong pid */
    117 	};
    118     }
    119 }
    120 
    121 #ifndef HAVE_DIRENT_H
    122 #include <sys/dir.h>
    123 #else
    124 #include <dirent.h>
    125 #endif
    126 
    127 void ss_add_info_dir(int sci_idx, char *info_dir, int *code_ptr)
    128 {
    129     register ss_data *info;
    130     DIR *d;
    131     int n_dirs;
    132     register char **dirs;
    133 
    134     info = ss_info(sci_idx);
    135     if (info_dir == NULL || *info_dir == '\0') {
    136 	*code_ptr = SS_ET_NO_INFO_DIR;
    137 	return;
    138     }
    139     if ((d = opendir(info_dir)) == (DIR *)NULL) {
    140 	*code_ptr = errno;
    141 	return;
    142     }
    143     closedir(d);
    144     dirs = info->info_dirs;
    145     for (n_dirs = 0; dirs[n_dirs] != (char *)NULL; n_dirs++)
    146 	;		/* get number of non-NULL dir entries */
    147     dirs = (char **)realloc((char *)dirs,
    148 			    (unsigned)(n_dirs + 2)*sizeof(char *));
    149     if (dirs == (char **)NULL) {
    150 	info->info_dirs = (char **)NULL;
    151 	*code_ptr = errno;
    152 	return;
    153     }
    154     info->info_dirs = dirs;
    155     dirs[n_dirs + 1] = (char *)NULL;
    156     dirs[n_dirs] = malloc((unsigned)strlen(info_dir)+1);
    157     strcpy(dirs[n_dirs], info_dir);
    158     *code_ptr = 0;
    159 }
    160 
    161 void ss_delete_info_dir(int sci_idx, char *info_dir, int *code_ptr)
    162 {
    163     register char **i_d;
    164     register char **info_dirs;
    165 
    166     info_dirs = ss_info(sci_idx)->info_dirs;
    167     for (i_d = info_dirs; *i_d; i_d++) {
    168 	if (!strcmp(*i_d, info_dir)) {
    169 	    while (*i_d) {
    170 		*i_d = *(i_d+1);
    171 		i_d++;
    172 	    }
    173 	    *code_ptr = 0;
    174 	    return;
    175 	}
    176     }
    177     *code_ptr = SS_ET_NO_INFO_DIR;
    178 }
    179