File: pcmcia.c

package info (click to toggle)
setserial 2.17-52
  • links: PTS, VCS
  • area: main
  • in suites: bullseye, buster, sid
  • size: 776 kB
  • sloc: sh: 2,127; ansic: 1,008; makefile: 150; csh: 2
file content (159 lines) | stat: -rw-r--r-- 4,514 bytes parent folder | download | duplicates (9)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

/* This file contains the modifications needed to check for pcmcia conflicts
 * between a normal port and a pcmcia serial-based port. Setserial should never
 * be permitted to control a pcmcia-based device... leave it to pcmcia-cs.
 *
 * Note that the checking is a bit of an overkill, in that I suspect that
 * checking stab is probably enough. However, far too many bugs have been
 * reported on this topic for me to cut corners, so all checks are in...
 *
 * - Gordon Russell <gor@debian.org>
 */

/* ...but I don't have a pcmcia system. I use some routines in a sub-directory
 * in the build directory to allow me to do some testing...
 */

extern char *progname;

#undef DEBUGPCMCIA
/* #define DEBUGPCMCIA */

#ifdef DEBUGPCMCIA
#define STABFILE {"pcmcia/var_run_stab",NULL}
#define CARDCTL "./pcmcia/cardctl"
#else
#define STABFILE {"/var/run/stab","/var/state/pcmcia/stab","/var/lib/pcmcia/stab",NULL}
#define CARDCTL "/sbin/cardctl"
#endif

/*
 * Just a check to make sure the device exists
 */
int safety_check(char *devname)
{
  if (access(devname,F_OK)) { 
     fprintf(stderr,"  %s: device is not found\n",devname);
     return 0;
  }
  return 1;
}

/*
 * check if the i/o address supplied for the port currently belongs to a
 * pcmcia i/o window using cardctl
 */
int pcmcia_check_cardctl(char *devname,int devport)
{
int filedes[2],pid; /* [0] is reading, [1] writing */
char *buffer;
char *i;
ssize_t sz;
int w,f,t,status;
int willreturn;
  willreturn=1;
  if (access(CARDCTL,F_OK)) return 1;
  if (pipe(filedes)==0) {
     switch(pid = fork()) {
       case -1 : fprintf(stderr," setserial: unable to check cardctl (fork)\n");
                 return 1;
       case 0  : /* child */
                 close(0); close(1); close(2);
                 close(filedes[0]);
                 dup2(filedes[1],1);
                 dup2(filedes[1],2); 
                 execl(CARDCTL,CARDCTL,"config",NULL);
                 /* printf("unable to execute %s\n",CARDCTL); */
                 exit(127);
       default : /* parent */
                 close(filedes[1]);
                 /* I need a buffer, but how big? Lets play safe... */
                 buffer = malloc(sizeof(char)*50000);
                 while ((sz = read(filedes[0],buffer,50000))) {
                    i = buffer;
                    while (i = strstr(i,"I/O window ")) {
                       if (sscanf(i,"I/O window %d: %x to %x,",&w,&f,&t)!=0) {
                         /* printf("%d 0x0%x 0x0%x\n",w,f,t); */
                         if ((devport>=f)&&(devport<=t)) {
                            fprintf(stderr,"  %s: port 0x0%x lies in pcmcia i/o window\n",devname,devport);
                            willreturn=0;
                         }
                       }
                       i++;
                    }
                 }
                 free(buffer);
                 close(filedes[0]);
     }
     if (waitpid(pid, &status, 0) == -1) {
       if (status != 0) {
         fprintf(stderr,"  setserial: strange response during cardctl command\n");
       }
     }
     return willreturn;
  } else {
    fprintf(stderr," setserial: unable to check cardctl (pipe)\n");
    return 1;
  }
}

/*
 * check that the device name specified is not being controlled by a
 * pcmcia manager as specified in the stab file
 */
int pcmcia_check_stab(char *devname)
{
char *i,**s,buffer[1024],dev[128];
int j;
FILE *stab;
char *stabs[] = STABFILE;

 for (s = stabs; *s; s++) { 
  /* printf("Scanning %s\n",*s); */
  if (!access(*s,F_OK))
    if ((stab = fopen(*s,"r"))!=NULL) {
      while (!feof(stab))
        if(fgets(buffer,1023,stab)) {
          i = strtok(buffer,"\t");
          for (j=0; (j<4)&&i; j++) i = strtok(NULL,"\t");
          if (i) {
            strcpy(dev,"/dev/");
            strcat(dev,i);
            /* Not perfect, since devname may not I suppose begin with a /dev */
            if (strcmp(dev,devname)==0) {
              fprintf(stderr,"  %s: pcmcia controlled device (%s)\n",
                  devname,*s);
              return 0;
            }
          }
        }
      fclose(stab);
    }
 }
 return 1;
}

const char *pcmcia_check(char *devname, int devport)
{
int len;
char *cname;
  if (safety_check(devname)) {
    if (pcmcia_check_stab(devname))
      if (pcmcia_check_cardctl(devname,devport))
        return "";
    return " pcmcia";
  }
  return "";
}

/*
main()
{
  pcmcia_check("/dev/ttyS0",0xa1f);
}
*/