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