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