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 (argc, argv, sci_idx, info_ptr)
     39     int argc;
     40     char const * const *argv;
     41     int sci_idx;
     42     pointer info_ptr;
     43 {
     44     char *buffer;
     45     char const *request_name;
     46     int code;
     47     int fd, child;
     48     register int idx;
     49     register ss_data *info;
     50 
     51     request_name = ss_current_request(sci_idx, &code);
     52     if (code != 0) {
     53 	ss_perror(sci_idx, code, "");
     54 	return;		/* no ss_abort_line, if invalid invocation */
     55     }
     56     if (argc == 1) {
     57 	ss_list_requests(argc, argv, sci_idx, info_ptr);
     58 	return;
     59     }
     60     else if (argc != 2) {
     61 	/* should do something better than this */
     62 	buffer = malloc(80+2*strlen(request_name));
     63 	if (!buffer) {
     64 		ss_perror(sci_idx, 0,
     65 			  "couldn't allocate memory to print usage message");
     66 		return;
     67 	}
     68 	sprintf(buffer, "usage:\n\t%s [topic|command]\nor\t%s\n",
     69 		request_name, request_name);
     70 	ss_perror(sci_idx, 0, buffer);
     71 	free(buffer);
     72 	return;
     73     }
     74     info = ss_info(sci_idx);
     75     if (info->info_dirs == (char **)NULL) {
     76 	ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
     77 	return;
     78     }
     79     if (info->info_dirs[0] == (char *)NULL) {
     80 	ss_perror(sci_idx, SS_ET_NO_INFO_DIR, (char *)NULL);
     81 	return;
     82     }
     83     for (fd = -1, idx = 0; info->info_dirs[idx] != (char *)NULL; idx++) {
     84         buffer = malloc(strlen (info->info_dirs[idx]) + 1 +
     85 			strlen (argv[1]) + 6);
     86 	if (!buffer) {
     87 	    ss_perror(sci_idx, 0,
     88 		      "couldn't allocate memory for help filename");
     89 	    return;
     90 	}
     91 	(void) strcpy(buffer, info->info_dirs[idx]);
     92 	(void) strcat(buffer, "/");
     93 	(void) strcat(buffer, argv[1]);
     94 	(void) strcat(buffer, ".info");
     95 	fd = open(buffer, O_RDONLY);
     96 	free(buffer);
     97 	if (fd >= 0)
     98 	    break;
     99     }
    100     if (fd < 0) {
    101 #define MSG "No info found for "
    102         char *buf = malloc(strlen (MSG) + strlen (argv[1]) + 1);
    103 	strcpy(buf, MSG);
    104 	strcat(buf, argv[1]);
    105 	ss_perror(sci_idx, 0, buf);
    106 	free(buf);
    107 	return;
    108     }
    109     switch (child = fork()) {
    110     case -1:
    111 	ss_perror(sci_idx, errno, "Can't fork for pager");
    112 	return;
    113     case 0:
    114 	(void) dup2(fd, 0); /* put file on stdin */
    115 	ss_page_stdin();
    116     default:
    117 	(void) close(fd); /* what can we do if it fails? */
    118 	while (wait(0) != child) {
    119 	    /* do nothing if wrong pid */
    120 	};
    121     }
    122 }
    123 
    124 #ifndef HAVE_DIRENT_H
    125 #include <sys/dir.h>
    126 #else
    127 #include <dirent.h>
    128 #endif
    129 
    130 void ss_add_info_dir(sci_idx, info_dir, code_ptr)
    131     int sci_idx;
    132     char *info_dir;
    133     int *code_ptr;
    134 {
    135     register ss_data *info;
    136     DIR *d;
    137     int n_dirs;
    138     register char **dirs;
    139 
    140     info = ss_info(sci_idx);
    141     if (info_dir == NULL || *info_dir == '\0') {
    142 	*code_ptr = SS_ET_NO_INFO_DIR;
    143 	return;
    144     }
    145     if ((d = opendir(info_dir)) == (DIR *)NULL) {
    146 	*code_ptr = errno;
    147 	return;
    148     }
    149     closedir(d);
    150     dirs = info->info_dirs;
    151     for (n_dirs = 0; dirs[n_dirs] != (char *)NULL; n_dirs++)
    152 	;		/* get number of non-NULL dir entries */
    153     dirs = (char **)realloc((char *)dirs,
    154 			    (unsigned)(n_dirs + 2)*sizeof(char *));
    155     if (dirs == (char **)NULL) {
    156 	info->info_dirs = (char **)NULL;
    157 	*code_ptr = errno;
    158 	return;
    159     }
    160     info->info_dirs = dirs;
    161     dirs[n_dirs + 1] = (char *)NULL;
    162     dirs[n_dirs] = malloc((unsigned)strlen(info_dir)+1);
    163     strcpy(dirs[n_dirs], info_dir);
    164     *code_ptr = 0;
    165 }
    166 
    167 void ss_delete_info_dir(sci_idx, info_dir, code_ptr)
    168     int sci_idx;
    169     char *info_dir;
    170     int *code_ptr;
    171 {
    172     register char **i_d;
    173     register char **info_dirs;
    174 
    175     info_dirs = ss_info(sci_idx)->info_dirs;
    176     for (i_d = info_dirs; *i_d; i_d++) {
    177 	if (!strcmp(*i_d, info_dir)) {
    178 	    while (*i_d) {
    179 		*i_d = *(i_d+1);
    180 		i_d++;
    181 	    }
    182 	    *code_ptr = 0;
    183 	    return;
    184 	}
    185     }
    186     *code_ptr = SS_ET_NO_INFO_DIR;
    187 }
    188